package com.ruoyi.framework.shiro.realm;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.framework.shiro.auth.CustomizedToken;
import com.ruoyi.framework.shiro.service.CommonAuthorizationService;
import com.ruoyi.system.domain.SysThird;
import com.ruoyi.system.service.ISysThirdService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.pac4j.core.profile.UserProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Objects;

/**
 * 认证与授权
 **/
public class Pac4jRealm extends AuthorizingRealm {
    private final static Logger log = LoggerFactory.getLogger(Pac4jRealm.class);

    @Autowired
    private CommonAuthorizationService commonAuthorizationService;

    @Autowired
    private ISysThirdService thirdService;


    /**
     * 授权
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return commonAuthorizationService.getAuthorizationInfo();
    }


    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {
        CustomizedToken customizedToken = (CustomizedToken) authenticationToken;
        UserProfile profile = customizedToken.getProfile();

        String st;
        try {
            Object stObj = profile.getAttribute("st");
            if (stObj instanceof List) {
                st = ((List<String>) stObj).get(0);
            } else {
                st = (String) stObj;
            }
        } catch (Exception e) {
            log.error("获取ST票据失败");
            st = "";
        }

        String username = profile.getId();
        SysUser user = commonAuthorizationService.getAndAddUserIfNotPresent(username);

        SysThird third = thirdService.selectThirdAuth();
        boolean ssoSync = Objects.equals(third.getSsoSync(), 0);

        if (ssoSync) {
            try {
                if (profile.containsAttribute("permissions")) {
                    List<String> permissions = (List<String>) profile.getAttribute("permissions");
                    user.setPermissionKeys(permissions);
                }

                if (profile.containsAttribute("roles")) {
                    List<String> roles = (List<String>) profile.getAttribute("roles");
                    user.setRoleKeys(roles);
                }
            } catch (Exception ignored) {
                log.error("获取权限数据失败");
            }
        }

        user.setSt(st);
        user.setClientName(profile.getClientName());
        return new SimpleAuthenticationInfo(user, profile.hashCode(), getName());
    }


    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof CustomizedToken;
    }

}
